package com.ruoyi.framework.config;

import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.annotation.ApiEncrypt;

/**
 * 解密请求体参数解析器
 * 只处理带有@RequestBody注解且需要解密的参数
 * 
 * @author ruoyi
 */
public class DecryptedRequestBodyArgumentResolver implements HandlerMethodArgumentResolver
{
    private static final Logger log = LoggerFactory.getLogger(DecryptedRequestBodyArgumentResolver.class);
    
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public boolean supportsParameter(MethodParameter parameter)
    {
        // 只处理带有@RequestBody注解的参数
        if (!parameter.hasParameterAnnotation(RequestBody.class))
        {
            return false;
        }
        
        Method method = parameter.getMethod();
        if (method == null)
        {
            return false;
        }
        
        // 获取类上的注解
        ApiEncrypt classAnnotation = parameter.getContainingClass().getAnnotation(ApiEncrypt.class);
        // 获取方法上的注解
        ApiEncrypt methodAnnotation = method.getAnnotation(ApiEncrypt.class);
        
        // 如果方法和类上都没有注解，则不支持
        if (classAnnotation == null && methodAnnotation == null)
        {
            return false;
        }
        
        // 优先使用方法上的注解，如果方法上没有注解，则使用类上的注解
        boolean requestDecrypt = methodAnnotation != null ? methodAnnotation.requestDecrypt() : classAnnotation.requestDecrypt();
        
        log.debug("参数解析器检查 - 方法: {}, 参数: {}, 有@RequestBody: true, requestDecrypt: {}", 
                method.getName(), parameter.getParameterName(), requestDecrypt);
        
        return requestDecrypt;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception
    {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        if (request == null)
        {
            log.warn("无法获取HttpServletRequest");
            return null;
        }
        
        String decryptedBody = (String) request.getAttribute("DECRYPTED_REQUEST_BODY");
        log.debug("从请求属性获取解密后的数据: {}", decryptedBody);
        
        if (decryptedBody == null || decryptedBody.isEmpty())
        {
            log.warn("解密后的请求体为空");
            return null;
        }
        
        try
        {
            Class<?> parameterType = parameter.getParameterType();
            log.debug("参数类型: {}", parameterType.getName());
            
            if (String.class.equals(parameterType))
            {
                log.debug("返回String类型参数: {}", decryptedBody);
                return decryptedBody;
            }
            else
            {
                Object result = objectMapper.readValue(decryptedBody, parameterType);
                log.debug("返回{}类型参数: {}", parameterType.getSimpleName(), result);
                return result;
            }
        }
        catch (Exception e)
        {
            log.error("参数解析失败 - 参数类型: {}, 解密数据: {}", parameter.getParameterType().getName(), decryptedBody, e);
            throw e;
        }
    }
}